﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Ionic.Zip;
using TorchView.Game;
using System.Text.RegularExpressions;

namespace TorchView.GameContent.Data
{
  /// <summary>
  /// Helper class used to read files from the pak.zip
  /// </summary>
  public static class PakReader
  {
    /// <summary>
    /// Open a copy of the file in the pak
    /// </summary>
    /// <param name="relativePath"></param>
    /// <returns></returns>
    public static Stream OpenFile(string relativePath)
    {
      using (ZipFile zipFile = new ZipFile(Torchlight.InstallDirectory + @"\Pak.zip"))
      {
        var entry = zipFile[relativePath];// zipFile.FirstOrDefault(z => string.Compare(z.FileName, relativePath, true) == 0);
        if (entry != null)
        {
          var stream = entry.OpenReader();
          byte[] buffer = new byte[(int)stream.Length];
          stream.Read(buffer, 0, buffer.Length);
          return new MemoryStream(buffer);
        }
      }
      return null;
    }

    /// <summary>
    /// Get the listing of files in the pak
    /// </summary>
    /// <param name="path"></param>
    /// <param name="searchPattern"></param>
    /// <param name="searchOption"></param>
    /// <returns></returns>
    public static IEnumerable<string> GetFiles(string path, string searchPattern = "*", SearchOption searchOption = SearchOption.TopDirectoryOnly)
    {
      if (path == null)
        throw new ArgumentNullException("path");
      if (searchPattern == null)
        throw new ArgumentNullException("searchPattern");

      if (path[path.Length - 1] != '/')
        path += "/";

      using (ZipFile zipFile = new ZipFile(Torchlight.InstallDirectory + @"\Pak.zip"))
      {
        foreach (var entry in zipFile.Where(z =>
        {
          if (z.IsDirectory
            || !z.FileName.StartsWith(path, StringComparison.InvariantCultureIgnoreCase)
            || (searchOption == SearchOption.TopDirectoryOnly && z.FileName.LastIndexOf('/', path.Length) > path.Length))
            return false;
          int index = z.FileName.LastIndexOf('/');

          string filename = index == -1 ? z.FileName : z.FileName.Substring(index + 1);
          return PassesFilter(filename, searchPattern);
        }))
          yield return entry.FileName;
      }
    }

    private static bool PassesFilter(string filename, string searchPattern)
    {
      var sections = searchPattern.Split(new char[] { '*' }, StringSplitOptions.None);

      int currentPosition = 0;
      for (int i = 0; i < sections.Length; i++)
      {
        var section = sections[i];
        if (section != string.Empty)
        {
          int index = filename.IndexOf(section, currentPosition, StringComparison.InvariantCultureIgnoreCase);
          if (index == -1)
            return false;
          else
            currentPosition = index + section.Length;
          if (i == sections.Length - 1)
            return currentPosition == filename.Length;
        }
      }
      return true;
    }
  }
}
